package com.c.cojbackendgateway.filter;

import com.c.cojbackendcommon.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

@Slf4j
@Component
public class GlobalAuthFilter implements GlobalFilter {

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    // 不需要验证token的路径
    private static final String[] WHITE_LIST = {
            "/api/user/login",
//            "/api/user/get/login",
            "/api/user/register",
            "/api/user/logout",
            "/api/doc.html",
            "/api/v3/api-docs",
            "/api/v2/api-docs",
            "/api/swagger-resources",
            "/api/swagger-ui.html",
            "/api/webjars/**",
            "/api/comment/v2/**",
            "/api/question/v2/**",
            "/api/judge/v2/**",
            "/api/user/v2/**",
    };

    /**
     * 判断是否为白名单路径
     * @param path 请求路径
     * @return 是否在白名单中
     */
    private boolean isWhiteListPath(String path) {
        for (String whitePath : WHITE_LIST) {
            if (antPathMatcher.match(whitePath, path)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest serverHttpRequest = exchange.getRequest();
        String path = serverHttpRequest.getURI().getPath();
        // 判断路径中是否包含 inner，只允许内部调用
        if (antPathMatcher.match("/**/inner/**", path)) {
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.FORBIDDEN);
            DataBufferFactory dataBufferFactory = response.bufferFactory();
            DataBuffer dataBuffer = dataBufferFactory.wrap("无权限".getBytes(StandardCharsets.UTF_8));
            return response.writeWith(Mono.just(dataBuffer));
        }
        // 统一权限校验，通过 JWT 获取登录用户信息
        //2. 公开接口（如登录注册）放行
        if (isWhiteListPath(path)){
            return chain.filter(exchange);
        }
        //3.验证 jwt
        String token = serverHttpRequest.getHeaders().getFirst("Authorization");
        if (StringUtils.isBlank(token) || !token.startsWith("Bearer ")) {
            return writeError(exchange.getResponse(), "未提供token");
        }
        try {
            token = token.substring(7);
            // 解析 JWT 并验证
            Claims claims = JwtUtils.parseToken(token);
            Long userId = Long.parseLong(claims.get("userId", String.class));
            String userRole = claims.get("userRole", String.class);

            //将用户信息添加到请求头中，传递给下游服务
            ServerHttpRequest newRequest = serverHttpRequest.mutate()
                    .header("X-user-Id", userId.toString())
                    .header("X-user-Role", userRole)
                    .build();
            return chain.filter(exchange.mutate().request(newRequest).build());
        } catch (Exception e) {
            return writeError(exchange.getResponse(), "Token无效或已过期");
        }
    }

    private Mono<Void> writeError(ServerHttpResponse response, String message) {
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        DataBuffer buffer = response.bufferFactory().wrap(message.getBytes(StandardCharsets.UTF_8));
        return response.writeWith(Mono.just(buffer));
    }


    private String getClientIp(ServerHttpRequest request) {
        HttpHeaders headers = request.getHeaders();

        // 优先级1：X-Forwarded-For（需处理多级代理）
        String xff = headers.getFirst("X-Forwarded-For");
        if (StringUtils.isNotEmpty(xff)) {
            String[] ips = xff.split(",");
            // 取第一个非 unknown 的IP
            for (String ip : ips) {
                ip = ip.trim();
                if (!"unknown".equalsIgnoreCase(ip)) {
                    return ip;
                }
            }
        }

        // 优先级2：X-Real-IP
        String xRealIp = headers.getFirst("X-Real-IP");
        if (StringUtils.isNotEmpty(xRealIp) && !"unknown".equalsIgnoreCase(xRealIp)) {
            return xRealIp;
        }

        // 优先级3：Proxy-Client-IP（针对Apache服务）
        String proxyClientIp = headers.getFirst("Proxy-Client-IP");
        if (StringUtils.isNotEmpty(proxyClientIp) && !"unknown".equalsIgnoreCase(proxyClientIp)) {
            return proxyClientIp;
        }

        // 优先级4：WL-Proxy-Client-IP（WebLogic）
        String wlProxyClientIp = headers.getFirst("WL-Proxy-Client-IP");
        if (StringUtils.isNotEmpty(wlProxyClientIp) && !"unknown".equalsIgnoreCase(wlProxyClientIp)) {
            return wlProxyClientIp;
        }

        // 最终回退：从TCP连接获取（仅在没有代理时有效）
        if (request.getRemoteAddress() != null) {
            return request.getRemoteAddress().getAddress().getHostAddress();
        }

        return "unknown";
    }
}
